import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Map;

import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

public class ServerRspThread implements Runnable {
	private int req_port;
	private ServerSocket req_server;
	private Socket req_s;
	private BufferedReader req_in;
	private PrintWriter req_out;
	private double signal_sum;	
	
	private MainWindow parent;

	public ServerRspThread(int port, MainWindow mw) {
		req_port = port;
		parent = mw;
	}

	@Override
	public void run() {
		req_server = null;
		try {
			req_server = new ServerSocket(req_port);
			System.out.println("Request server created!");
			req_s = req_server.accept();
			System.out.println("Request server accepted!");
			req_in = new BufferedReader(new InputStreamReader(
					req_s.getInputStream()));
			req_out = new PrintWriter(req_s.getOutputStream());
			boolean end_flag = false;
			while (!end_flag) {
				String line = req_in.readLine();
				System.out.println("line= " + line);
				String[] req_head = line.split(" ");
				if (req_head.length == 2){
					String header = req_head[0];
					System.out.println("header= " + header);
					int header_code = Integer.parseInt(req_head[1]);
					System.out.println("header code= " + header_code);
					String ans = "";
					if (header.equals("request")) {
						switch (header_code) {
						case 0:// request type: handshaking message
							ans = route();
							req_out.println(ans);
							req_out.flush();
							System.out.println("Route sends back: " + ans);
							break;
						case -1:
							end_flag = true;
							System.out.println("ReqServer says: byebye!");
							break;
						}
					}
				}
			}
			req_s.close();
		} catch (Exception e) {
			System.out.println("Can not listen to:" + e);
		}
		System.out.println("Server ended!");
	}

	private String route() {
		String decision = null;
		try {
			String line = req_in.readLine();
			System.out.println("route line= " + line);
			//fetch client info
			String[] client_inf = line.split(" ");
			if (client_inf.length == 3){
				String client_name = client_inf[0];
				String client_wifiIP = client_inf[1];
				double client_signal = Double.parseDouble(client_inf[2]);
				String client_G3IP = req_s.getInetAddress().getHostAddress();
				signal_sum = client_signal;
				System.out.println("client name = " + client_name + " client wifiIP = "
						+ client_wifiIP + " client_3GIP = " + client_G3IP + " client_signal = " + client_signal);
				//put into Map clients
				Client client = new Client(client_name, client_wifiIP, client_G3IP, client_signal);
				System.out.println("after create client");
				MainWindow.clients.put(client_wifiIP, client);
				System.out.println("after put");
				
				//continue to read client info
				while (!client_name.equals("-1")) {
					line = req_in.readLine();
					//System.out.println("in while, after readline: " + line);
					client_inf = line.split(" ");
					if (client_inf.length == 3){
						client_name = client_inf[0];
						if (client_name.equals("-1")) { 
							//System.out.println("length3 break");
							break;
						}
						client_wifiIP = client_inf[1];
						client_signal = Double.parseDouble(client_inf[2]);
						
						signal_sum += client_signal;
						System.out.println("client name= " + client_name + " client wifiIP= "
								+ client_wifiIP /*+ " client_3GIP = " + client_G3IP*/ + " client_signal= " + client_signal);
						//put into Map clients
						client = new Client(client_name,client_wifiIP, " ", client_signal);
						MainWindow.clients.put(client_wifiIP, client);
						//add new row in table						
					}else{
						//System.out.println("else -1");
						client_name = "-1";
					}
				}
				//refresh infTable in MainWindow
				refreshInfTable();
				//Make route decision
				decision = makeRouteDecision();
				System.out.println("route 3");
				// s.shutdownInput();
			}	
			System.out.println("route ended!");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			System.out.println("Error: route: readLine");
		}
		return decision;
	}

	private String makeRouteDecision() {
		String decision="";
		int startPosition = 0;
		int endPosition = 0;
		decision += "response 0\n";
		Iterator iter = MainWindow.clients.entrySet().iterator();
		while (iter.hasNext()){
			Map.Entry<String, Client> entry = (Map.Entry<String, Client>)iter.next();
			Client client = entry.getValue();
			//decision += client.getName() + " " + client.getWifiIP() + " " + client.getG3IP() + " " + parent.fileName + " ";
			int size = (int) (client.getSigIntensity() / signal_sum * parent.fileSize_Bytes);
			endPosition = startPosition + size;
			if (endPosition > parent.fileSize_Bytes) endPosition = parent.fileSize_Bytes;
			//decision += startPosition + " " + endPosition + "\n";
			client.setStartPosition(startPosition);
			client.setEndPosition(endPosition);
			client.setDownloadSize(size);
			startPosition = endPosition + 1;
		}
		refreshInfTable();
		//decision += "-1 -1\n";
		decision += getFileName(parent.fileName);
		return decision;
	}
	
	private String getFileName(String fileName) {
		String[] filePath = fileName.split("\\\\");
		String filename = filePath[filePath.length-1];
		System.out.println("getFileName: " + filename);
		return filename;
	}

	private void refreshInfTable() {
		// clear table
		//System.out.println("clearTable begin");
		try{
			DefaultTableModel tableModel = new DefaultTableModel();
			Object[][] tableData = {};
			Object[] columnTitle = { "Client No.", "WiFi IP Address", "3G IP Address", "Signal Intensity",
					"Start Position", "End Position", "Download Size"};
			tableModel.setDataVector(tableData, columnTitle);
			parent.infTable.setModel(tableModel);
		}catch (Exception e){
			e.printStackTrace();
		}
		//System.out.println("clearTable end");
		//refill table
		DefaultTableModel tableModel = (DefaultTableModel) parent.infTable.getModel();
		String[] row = new String[7];
		for (Client client : MainWindow.clients.values()){
			row[0] = client.getName();
			row[1] = client.getWifiIP();
			row[2] = client.getG3IP();
			row[3] = String.valueOf(client.getSigIntensity());
			row[4] = String.valueOf(client.getStartPosition());
			row[5] = String.valueOf(client.getEndPosition());
			row[6] = String.valueOf(client.getDownloadSize());
			tableModel.addRow(row);
		}
	}
}
